#include "head.h"

// 功能：获取pwd
int getPwd(MYSQL *mysql, int userId){
    char sql[1024];
    bzero(sql, sizeof(sql));

    sprintf(sql, "select pwd from user_info where id = %d;", userId);
    int ret = mysql_query(mysql, sql);
    if(ret != 0){
        return -1;
    }
    MYSQL_RES *res = mysql_store_result(mysql);
    MYSQL_ROW row = mysql_fetch_row(res);

    int pwd = atoi(row[0]);

    return pwd;
}

// 功能：获取文件绝对路径
int getAbsolutionPath(MYSQL *mysql, int pwd, char *fileName, char *path){
    char sql[1024];
    bzero(sql, sizeof(sql));

    sprintf(sql, "select path from file_info where id = %d;", pwd);
    int ret = mysql_query(mysql, sql);
    if(ret != 0){
        return -1;
    }

    MYSQL_RES *res = mysql_store_result(mysql);
    MYSQL_ROW row = mysql_fetch_row(res);

    memcpy(path, row[0], strlen(row[0]));
    
    int len = strlen(row[0]);
    if(row[0][len-1] != '/'){
        strcat(path, "/");
    }

    strcat(path, fileName);
    return 0;
}

// 功能：处理下载(已重构)                              
//int dealGets(MYSQL *mysql, int sockfd, train_t *mess, threadPool_t *threadPool){
//    // 接收客户端已有文件大小
//    train_t train;
//    recvRequest(sockfd, &train);
//
//    // 查表，看文件是否存在
//    int userId = threadPool->recordUserId[sockfd];
//    char sql[8192];
//    bzero(sql, sizeof(sql));
//
//    sprintf(sql, "select fileMd5Value from file_info where fileName = '%s' and (select 1 from user_info where pwd = parentId and id = %d);", mess->buf, userId);
//
//
//    int ret = mysql_query(mysql, sql);
//    if(ret != 0){
//        TLVResponse(sockfd, mysql_error(mysql), IS_NOT_OK);
//        return -1;
//    }
//    // 对查询结果进行分析
//    MYSQL_RES *res = mysql_store_result(mysql);
//
//    // 查询返回0行，说明没有此文件
//    int row = mysql_num_rows(res);
//    if(row == 0){
//        TLVResponse(sockfd, "file is not exist", IS_NOT_OK);
//        return -1;
//    }
//    // md5值为空，说明是文件目录，无法下载，响应失败
//    MYSQL_ROW rowRet = mysql_fetch_row(res);
//    if(rowRet[0] == NULL){
//        TLVResponse(sockfd, "The directory cannot be downloaded.", IS_NOT_OK);
//        return -1;
//    }
//    // 文件存在情况
//    int fd = open(rowRet[0], O_RDWR);
//    int fileSize = lseek(fd, 0, SEEK_END);
//    lseek(fd, 0, SEEK_SET);
//    off_t curSize = train.len;
//
//    // 响应客户端将要传送到少字节文件
//    TLVResponseLen(sockfd, fileSize - curSize); 
//
//    ftruncate(fd, fileSize);
//
//    sendfile(sockfd, fd, &curSize, fileSize - curSize);
//
//    close(fd);
//
//    return 0;
//}
//
//// 功能：处理上传(已重构)
//int dealPuts(MYSQL *mysql, int sockfd, train_t *mess, threadPool_t *threadPool){
//    // 路径合法性判断
//    if(mess->buf[0] == '/'){
//        // 使用绝对路径，进行合理性判断
//       // if(isLegalPath(mysql, mess->buf) != 0){
//       //     TLVResponse(sockfd, "path error", IS_NOT_OK);
//       //     return -1;
//       // }
//    }
//
//    printf("fileName :%s\n",mess->buf );
//
//    // 获取文件MD5值
//    train_t md5Num;
//    recvRequest(sockfd, &md5Num);
//    // 获取客户端文件大小
//    train_t len;
//    recvRequest(sockfd, &len);
//    
//    printf("md5Num :%s\n", md5Num.buf);
//
//    int userId = threadPool->recordUserId[sockfd];
//    // 先查询当前目录下，看是否存在此文件
//    char sql[20480];
//    bzero(sql, sizeof(sql));
//
//    // 获取当前所在目录，拼接文件绝对路径
//    int pwd = getPwd(mysql, userId);
//    printf("userId : %d\n", userId);
//    printf("pwd : %d\n",pwd);
//
//    char absolutionPath[1024];
//
//
//    bzero(absolutionPath, sizeof(absolutionPath));
//    getAbsolutionPath(mysql, pwd, mess->buf, absolutionPath);
//    
//    printf("path : %s\n", absolutionPath);
//
//    sprintf(sql, "select fileMd5Value from file_info where fileName = '%s' and (select 1 from user_info where id = %d and parentId = pwd);", mess->buf, userId);
//    
//    /* printf("sql : %s\n",sql); */
//
//    // 如果当前文件夹下没有此文件,需插入
//    int ret = mysql_query(mysql, sql);
//    if(ret != 0){
//        TLVResponse(sockfd, mysql_error(mysql), IS_NOT_OK);
//        return -1;
//    }
//    // 看查表结果
//    MYSQL_RES *res = mysql_store_result(mysql);
//    int row = mysql_num_rows(res);
//
//    printf("ret row : %d\n", row);
//    
//    if(row == 0){
//        bzero(sql, sizeof(sql));
//        // 插入
//        sprintf(sql, "insert into file_info (fileName, parentId, fileMd5Value, userId, path, fileType) value('%s', %d, '%s', %d, '%s', 'f');", mess->buf, pwd, md5Num.buf, userId, absolutionPath);
//        ret = mysql_query(mysql, sql);
//
//        if(ret != 0){
//            TLVResponse(sockfd, mysql_error(mysql), IS_NOT_OK);
//            return -1;
//        }
//        // 插入成功
//        printf("insert success\n");
//    }
//    int fd = open(md5Num.buf, O_RDWR | O_CREAT, 0666);
//    int fileSize = lseek(fd, 0, SEEK_END);
//    lseek(fd, 0, SEEK_SET);
//
//    printf("filesize : %d\n", len.len);
//
//    if(len.len == fileSize){
//        // 服务以有此文件，秒传
//        printf("quick put\n");
//        TLVResponse(sockfd, "puts success", IS_OK);
//        return 0;
//    }
//    // 服务端没有此文件或者文件不全,响应已有文件大小
//    TLVResponseLen(sockfd, fileSize);
//
//    // 获取客户端要上传文件的大小
//    recvRequest(sockfd, &len);
//    printf("client send %d\n", len.len);
//    
//    ftruncate(fd, fileSize + len.len);
//
//    char *buf = (char *)mmap(NULL, fileSize + len.len, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
//    recv(sockfd, buf + fileSize, len.len, MSG_WAITALL);
//
//    TLVResponse(sockfd, "puts success", IS_OK);
//    
//
//    return 0;
//}   


/**
 * 处理文件上传命令
 * @param mysql MySQL数据库连接指针
 * @param userid 用户ID
 * @param sockfd 客户端套接字
 * @param destPath 目标路径字符串
 * @return 成功返回0，失败返回-1
 */
int putsOrder(MYSQL *mysql, int userid, int sockfd, char *destPath){
    int destPos;  // 目标目录ID
    char parent[1024] = {0};  // 父目录路径
    char toPut[1024] = {0};   // 要上传的文件名
    
    // 分割路径为父目录和文件名
    divPath(parent, toPut, destPath);
    
    // 查找父目录ID
    int ret = findPath(mysql, userid, sockfd, parent, &destPos);
    if(ret == -1){
        return -1;  // 路径查找失败
    }
    
    // 发送服务器地址和端口给客户端
    char buf[1024] = {0};
    sprintf(buf, "%s/%s", IP_ADDR1, PORT1);
    TLVResponse(sockfd, buf, IPADDR_PORT);
    
    // 接收客户端发送的文件MD5值
    train_t train;
    bzero(&train, sizeof(train_t));
    recvOrderTrain(sockfd, &train);
    char MD5[1024] = {0};
    strcpy(MD5, train.buf);
    
    // 检查文件是否已存在
    char sql[1024] = {0};
    bzero(sql, 1024);
    sprintf(sql, "select count(*) from file_info where parentId = %d and fileName = '%s';", destPos, toPut);
    
    printf("%s\n", sql);

    mysql_query(mysql, sql);
    MYSQL_RES *rows = mysql_store_result(mysql);
    MYSQL_ROW row = mysql_fetch_row(rows);
    
    // 如果文件不存在，创建新记录
    if(atoi(row[0]) == 0){
        char newPath[1024] = {0};
        bzero(sql, 1024);
        // 获取父目录完整路径
        sprintf(sql, "select path from file_info where id = %d;", destPos);
        mysql_query(mysql, sql);
        rows = mysql_store_result(mysql);
        MYSQL_ROW row = mysql_fetch_row(rows);
        // 构建新文件路径
        sprintf(newPath, "%s/%s", row[0], toPut);
        
        // 插入新文件记录
        bzero(sql, 1024);
        sprintf(sql, "insert into file_info values (null, '%s', %d, '%s', %d, '%s', 'f');", 
                toPut, destPos, MD5, userid, newPath);
        mysql_query(mysql, sql);
    }
    return 0;
}



/**
 * 处理文件下载命令
 * @param mysql MySQL数据库连接指针
 * @param userid 用户ID
 * @param sockfd 客户端套接字
 * @param destPath 目标路径字符串
 * @return 成功返回0，失败返回-1
 */
int getsOrder(MYSQL *mysql, int userid, int sockfd, char *destPath, int dLdSvrSockfd){
    int destPos;  // 目标目录ID
    char parent[1024] = {0};  // 父目录路径
    char toGet[1024] = {0};   // 要下载的文件名
    
    // 分割路径为父目录和文件名
    divPath(parent, toGet, destPath);
    
    // 查找父目录ID
    int ret = findPath(mysql, userid, sockfd, parent, &destPos);
    if(ret == -1){
        return -1;  // 路径查找失败
    }
    
    // 查询文件的MD5值
    char sql[1024] = {0};
    sprintf(sql, "select fileMD5Value from file_info where parentId = %d and fileName = '%s';", destPos, toGet);
    mysql_query(mysql, sql);
    MYSQL_RES *rows = mysql_store_result(mysql);
    
    // 检查文件是否存在
    if((int)mysql_num_rows(rows) == 0){
        RETERROR2("No such file.");  // 文件不存在
        return -1;
    }
    
    // 获取文件MD5值并发送给客户端
    MYSQL_ROW row = mysql_fetch_row(rows);
    char MD5[1024] = {0};
    strcpy(MD5, row[0]);
    TLVResponse(sockfd, MD5, IS_OK);
    
    //向下载服发送MD5值查询文件大小
    TLVResponse(dLdSvrSockfd, MD5, FILE_LEN);
    train_t train;
    bzero(&train, sizeof(train_t));
    recvOrderTrain(dLdSvrSockfd, &train);
    char fileSize[16] = {0};
    strcpy(fileSize, train.buf);

    printf("fileSize : %s\n", train.buf);

    TLVResponse(sockfd, fileSize, FILE_LEN);
    
    // 发送服务器地址和端口给客户端
    char buf[1024] = {0};
    sprintf(buf, "%s/%s/%s/%s/%s/%s", IP_ADDR1, PORT1, IP_ADDR2, PORT2, IP_ADDR3, PORT3);
    TLVResponse(sockfd, buf, IPADDR_PORT);
    
    return 0;
}

